﻿#region Using Statements
using System;
using System.Diagnostics;
using GameBase.Screens;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
#endregion

namespace StarFox.ScreenComponents
{
    /// <summary>
    /// Implementation of a head-up display.
    /// <para>Definition of Update() method.</para>
    /// </summary>
    partial class HeadUpDisplay
    {
        /// <summary>
        /// Called when the ScreenComponent2D needs to be updated.
        /// </summary>
        /// <param name="gameTime">Time elapsed since the last call to this method.</param>
        public override void Update(GameTime gameTime)
        {
            #region Screen Transitions

            if (toVisible)
            {
                // update items position
                float auxTrTime = 1.0f - (float)Math.Pow(1.0f - trTime, 2);
                // HUD - Fuel
                dstRectFuel.X = initPosFuel.X + (int)(Math.Abs(initPosFuel.X - endPosFuel.X) * auxTrTime);
                // HUD - Health
                dstRectHealth.X = initPosHealth.X + (int)(Math.Abs(initPosHealth.X - endPosHealth.X) * auxTrTime);
                // HUD - Boost
                dstRectBoost.X = initPosBoost.X + (int)(Math.Abs(initPosBoost.X - endPosBoost.X) * auxTrTime);
                // HUD - Bombs
                dstRectBomb.X = initPosBomb.X + (int)(Math.Abs(initPosBomb.X - endPosBomb.X) * auxTrTime);
                // HUD - Lives
                posLives.Y = initPosLives.Y + Math.Abs(initPosLives.Y - endPosLives.Y) * auxTrTime;
                // HUD - Score
                posScore.Y = initPosScore.Y + Math.Abs(initPosScore.Y - endPosScore.Y) * auxTrTime;
                // HUD - Ship
                posShip.X = initPosShip.X - (int)(Math.Abs(initPosShip.X - endPosShip.X) * auxTrTime);
                
                // update transition timer
                float trDelta = (float)(gameTime.ElapsedGameTime.TotalMilliseconds / Time.TotalMilliseconds);
                trTime += trDelta;
                trTime = MathHelper.Clamp(trTime, 0.0f, 1.0f);
                if (trTime == 1.0f) { toVisible = false; trTime = 0.0f; }
            }
            else if (toHidden)
            {
                // update items position
                float auxTrTime = (float)Math.Pow(trTime, 2);
                // HUD - Fuel
                dstRectFuel.X = endPosFuel.X - (int)(Math.Abs(initPosFuel.X - endPosFuel.X) * auxTrTime);
                // HUD - Health
                dstRectHealth.X = endPosHealth.X - (int)(Math.Abs(initPosHealth.X - endPosHealth.X) * auxTrTime);
                // HUD - Boost
                dstRectBoost.X = endPosBoost.X - (int)(Math.Abs(initPosBoost.X - endPosBoost.X) * auxTrTime);
                // HUD - Bombs
                dstRectBomb.X = endPosBomb.X - (int)(Math.Abs(initPosBomb.X - endPosBomb.X) * auxTrTime);
                // HUD - Lives
                posLives.Y = endPosLives.Y - Math.Abs(initPosLives.Y - endPosLives.Y) * auxTrTime;
                // HUD - Score
                posScore.Y = endPosScore.Y - Math.Abs(initPosScore.Y - endPosScore.Y) * auxTrTime;
                // HUD - Ship
                posShip.X = endPosShip.X + (int)(Math.Abs(initPosShip.X - endPosShip.X) * auxTrTime);
                
                // update transition timer
                float trDelta = (float)(gameTime.ElapsedGameTime.TotalMilliseconds / Time.TotalMilliseconds);
                trTime += trDelta;
                trTime = MathHelper.Clamp(trTime, 0.0f, 1.0f);
                if (trTime == 1.0f) { toHidden = false; trTime = 0.0f; }
            }

            #endregion

            if (Screen.Paused)
                return;

            #region Cross-Hair

            Vector3 crossHairVector = new Vector3(camera.Up.X, camera.Up.Y, 0);
            crossHairVector.Normalize();

            crossHairAngle = (float)Math.Acos((double)Vector3.Dot(crossHairVector, Vector3.Up));
            crossHairAngle = (crossHairVector.X < 0) ? -crossHairAngle : crossHairAngle;

            Vector3 shipVector = new Vector3(camera.Forward.X, 0, camera.Forward.Z);
            shipVector.Normalize();

            shipAngle = (float)Math.Acos((double)Vector3.Dot(shipVector, Vector3.Forward));
            shipAngle = (shipVector.X < 0) ? -shipAngle : shipAngle;

            posCrossHair_Bar_Bottom_Left.X = (0.280f + 0.1f * speed) * Screen.Width;
            posCrossHair_Bar_Top_Left.X = (0.280f + 0.1f * speed) * Screen.Width;
            posCrossHair_Bar_Bottom_Right.X = (0.720f - 0.1f * speed) * Screen.Width;
            posCrossHair_Bar_Top_Right.X = (0.720f - 0.1f * speed) * Screen.Width;

            posCrossHair_Bar_Bottom_Left.Y = (0.535f - 0.03f * speed) * Screen.Height;
            posCrossHair_Bar_Top_Left.Y = (0.465f + 0.03f * speed) * Screen.Height;
            posCrossHair_Bar_Bottom_Right.Y = (0.535f - 0.03f * speed) * Screen.Height;
            posCrossHair_Bar_Top_Right.Y = (0.465f + 0.03f * speed) * Screen.Height;

            #endregion

            #region Collisions

            if (isDanger_Left)
            {
                float timeDelta = (float)(gameTime.ElapsedGameTime.TotalMilliseconds / WarningEffectDuration.TotalMilliseconds);
                dangerTime_Left += timeDelta;
                dangerTime_Left = MathHelper.Clamp(dangerTime_Left, 0.0f, 1.0f);
                if (dangerTime_Left == 1.0f) { isDanger_Left = false; dangerTime_Left = 0.0f; }

                dangerAlpha_Left = 1.0f - (float)Math.Pow(dangerTime_Left, 2);
            }

            if (isDanger_Center)
            {
                float timeDelta = (float)(gameTime.ElapsedGameTime.TotalMilliseconds / WarningEffectDuration.TotalMilliseconds);
                dangerTime_Center += timeDelta;
                dangerTime_Center = MathHelper.Clamp(dangerTime_Center, 0.0f, 1.0f);
                if (dangerTime_Center == 1.0f) { isDanger_Center = false; dangerTime_Center = 0.0f; }

                dangerAlpha_Center = 1.0f - (float)Math.Pow(dangerTime_Center, 2);
            }

            if (isDanger_Right)
            {
                float timeDelta = (float)(gameTime.ElapsedGameTime.TotalMilliseconds / WarningEffectDuration.TotalMilliseconds);
                dangerTime_Right += timeDelta;
                dangerTime_Right = MathHelper.Clamp(dangerTime_Right, 0.0f, 1.0f);
                if (dangerTime_Right == 1.0f) { isDanger_Right = false; dangerTime_Right = 0.0f; }

                dangerAlpha_Right = 1.0f - (float)Math.Pow(dangerTime_Right, 2);
            }

            #endregion

            #region Bomb Mode

            if (isBombMode)
            {
                float timeDelta = (float)(gameTime.ElapsedGameTime.TotalMilliseconds / BombModeDuration.TotalMilliseconds);
                bombModeTime += timeDelta;
                bombModeTime = MathHelper.Clamp(bombModeTime, 0.0f, 1.0f);
                if (bombModeTime == 1.0f) { isBombMode = false; bombModeTime = 0.0f; }

                bombModeBar.Value = 1.0f - bombModeTime;
            }

            #endregion          
        }
    }
}
